package com.it2297.component;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;
import javax.swing.border.EmptyBorder;

import com.alee.extended.image.WebImage;
import com.it2297.util.ImageProcessor;

@SuppressWarnings("serial")
public class ImageCropper extends JDialog
{
	private int originX;
	private int originY;
	private int endX;
	private int endY;
	private BufferedImage bimg;
	private BufferedImage originBimg;

	private final JPanel contentPanel = new JPanel();
	private final JPanel canvas = new JPanel();
	private final WebImage wimg;
	private final JToolBar toolBar = new JToolBar();
	private final JLabel lblW = new JLabel("w:");
	private final JLabel lblH = new JLabel("h:");
	private final JLabel lblX = new JLabel("x:");
	private final JLabel lblY = new JLabel("y:");
	private final JButton btnCrop = new JButton("Crop");
	private final Component horizontalStrut = Box.createHorizontalStrut(20);
	private final JButton btnResize = new JButton("Resize");
	private final JScrollPane scrollPane = new JScrollPane();
	private final JButton btnSaveClose = new JButton("Done");
	private final JButton btnReset = new JButton("Reset");

	public ImageCropper(BufferedImage inputBimg)
	{
		this.originBimg = inputBimg;
		this.bimg = inputBimg;

		wimg = new WebImage(new ImageIcon(bimg))
		{
			@Override
			public void paint(Graphics g)
			{
				super.paint(g);
				Graphics2D g2d = (Graphics2D) g;
				g2d.setStroke(new BasicStroke(1F, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 3F, new float[] { 5F, 5F }, 0F));
				g.drawRect(originX, originY, endX - originX, endY - originY);
			}
		};

		initGUI();
	}

	private void initGUI()
	{
		setBounds(100, 100, 1000, 700);
		setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
		setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
		setLocationRelativeTo(null);
		getContentPane().setLayout(new BorderLayout());
		contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
		getContentPane().add(contentPanel, BorderLayout.CENTER);
		contentPanel.setLayout(new BorderLayout(0, 0));
		canvas.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5));
		canvas.add(wimg);
		toolBar.setFloatable(false);

		contentPanel.add(toolBar, BorderLayout.NORTH);
		btnCrop.setIcon(new ImageIcon(ImageCropper.class.getResource("/com/alee/extended/ninepatch/icons/guidelines.png")));
		btnCrop.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent arg0)
			{
				int selectionWidth = endX - originX;
				int selectionHeight = endY - originY;

				if (selectionWidth > 0 && selectionHeight > 0)
				{
					try
					{

						bimg = ImageProcessor.cropImage(bimg, originX, originY, selectionWidth, selectionHeight);
						wimg.setImage(bimg);

					}
					catch (IllegalArgumentException e)
					{
						// probably 0 or negative width and height
						bimg = null;
					}
				}
				else
				{
					bimg = null;
				}
				clearSelection();
			}
		});

		toolBar.add(btnCrop);
		btnResize.setIcon(new ImageIcon(ImageCropper.class.getResource("/com/alee/utils/icons/color/color.png")));
		btnResize.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent arg0)
			{
				try
				{
					int width = Integer.parseInt(JOptionPane.showInputDialog("Enter width:"));
					int height = Integer.parseInt(JOptionPane.showInputDialog("Enter height:"));

					bimg = ImageProcessor.resize(bimg, width, height, false, false);
					wimg.setImage(bimg);
					clearSelection();
				}
				catch (Exception ex)
				{
					// bad inputs
				}
			}
		});

		toolBar.add(btnResize);
		btnSaveClose.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				close();
			}
		});
		btnReset.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				bimg = originBimg;
				wimg.setImage(bimg);
				clearSelection();
			}
		});
		btnReset.setIcon(new ImageIcon(ImageCropper.class.getResource("/com/alee/extended/filechooser/icons/refresh.png")));

		toolBar.add(btnReset);
		btnSaveClose.setIcon(new ImageIcon(ImageCropper.class.getResource("/com/alee/extended/filechooser/icons/ok.png")));

		toolBar.add(btnSaveClose);

		toolBar.add(horizontalStrut);
		lblW.setPreferredSize(new Dimension(100, 15));

		toolBar.add(lblW);
		lblH.setPreferredSize(new Dimension(100, 15));

		toolBar.add(lblH);
		lblX.setPreferredSize(new Dimension(100, 15));

		toolBar.add(lblX);
		lblY.setPreferredSize(new Dimension(100, 15));

		toolBar.add(lblY);

		contentPanel.add(scrollPane, BorderLayout.CENTER);

		scrollPane.setViewportView(canvas);

		wimg.addMouseListener(new MouseAdapter()
		{
			@Override
			public void mousePressed(MouseEvent arg0)
			{
				originX = arg0.getX();
				originY = arg0.getY();
			}

		});
		wimg.addMouseMotionListener(new MouseAdapter()
		{
			@Override
			public void mouseMoved(MouseEvent arg0)
			{
				updateInfo(arg0);
			}

			@Override
			public void mouseDragged(MouseEvent arg0)
			{
				updateInfo(arg0);
				endX = arg0.getX();
				endY = arg0.getY();
				wimg.repaint();
			}
		});
	}

	public BufferedImage getResultImage()
	{
		return bimg;
	}

	private void updateInfo(MouseEvent arg0)
	{
		int selectionWidth = endX - originX;
		int selectionHeight = endY - originY;

		lblW.setText("w: " + wimg.getWidth() + " (" + selectionWidth + ")");
		lblH.setText("h: " + wimg.getHeight() + " (" + selectionHeight + ")");
		lblX.setText("x: " + arg0.getX());
		lblY.setText("y: " + arg0.getY());
	}

	private void clearSelection()
	{
		endX = 0;
		endY = 0;
		originX = 0;
		originY = 0;
		wimg.repaint();
	}

	private void close()
	{
		this.dispose();
	}
}
